'use strict';

import { Service } from 'egg'
import { ModelStatus } from '../model/types'

export default class DataService extends Service {

  // 根据ID获取UUID
  async getUUIDWithId(id: string) {
    const { Enum } = this.ctx.model as any;
    const enumModel = await Enum.findWithId(id)
    return enumModel.uuid
  }

  // 根据数据ID获取UUID
  async getUUIDWithDataId(id: string) {
    const { Data } = this.ctx.model as any;
    const dataModel = await Data.findWithId(id)
    return this.getUUIDWithId(dataModel.menuId)
  }

  /**
   * 创建数据(创建新数据)
   */
  public async createDataModel(data: string, projectId: string, enumId: string, index = 0, superId?: string) {
    const { Data } = this.ctx.model as any;
    const { ctx } = this
    // 获取用户数据
    const userData = await ctx.getUserData()
    return new Data({
      data,
      createTime: new Date(),
      createUser: userData._id,
      superId,
      enumId,
      index,
      project: projectId
    }).save()
  }

  /**
   * 创建数据(旧数据的历史记录)
   */
  public async createRecordModel(dataModel) {
    const { Data } = this.ctx.model as any;
    return new Data({
      data: dataModel.data,
      createTime: dataModel.createTime,
      createUser: dataModel.createUser,
      superId: dataModel._id,
      enumId: dataModel.enumId,
      project: dataModel.project,
    }).save()
  }

  /**
   * 保存当前数据，并添加记录
   */
  public async restoreData(currentData: any, data: string, index = 0) {
    const { ctx } = this
    // 获取用户数据
    const userData = await ctx.getUserData()
    // 创建旧数据
    await this.createRecordModel(currentData)
    // 替换新数据
    currentData.data = data
    currentData.createTime = new Date()
    currentData.createUser = userData._id
    currentData.index = index
    currentData.save()
  }

  /**
   * 初始化数据(单条数据)
   */
  public async initOneData(enumModel, data) {
    const newData = await this.createDataModel(data, enumModel.project, enumModel._id)
    enumModel.data = newData._id
    await enumModel.save()
    return newData
  }

  /**
   * 更新单条数据
   */
  public async updateOne(id, { data, createTime }) {
    const { Enum, Data } = this.ctx.model as any;
    const enumModel = await Enum.findWithId(id)
    // 判断是否有enum
    if (!enumModel) {
      throw 'UUID 有误'
    }
    // 判断是否有旧数据
    if (enumModel.data) {
      // 获取当前数据
      const currentData = await Data.findWithId(enumModel.data)
      // 判断之前是否有人存储数据
      const newDateNum = createTime ? new Date(createTime).getTime() : -1
      const ondDateNum = currentData.createTime.getTime()
      // 时间不同，提示合并冲突
      if (newDateNum !== ondDateNum) {
        throw '有修改，请刷新当前界面，重新提交数据'
      }
      await this.restoreData(currentData, data)
      return [currentData, enumModel]
    } else {
      // 没有数据创建新数据
      const dataModel = await this.initOneData(enumModel, data)
      return [dataModel, enumModel]
    }
  }

  /**
   * 获取单条数据
   */
  public async getOne(id: string) {
    const { Enum } = this.ctx.model as any;
    const enumModel = await Enum.findOneDataWithId(id)
    if (!enumModel.data) {
      throw '请先初始化当前数据'
    }
    return enumModel.data
  }

  /**
   * 获取单条数据
   */
  public async getOneData(uuid: string) {
    const { Enum } = this.ctx.model as any;
    const enumModel = await Enum.findOneDataWithUUID(uuid)
    if (!enumModel.data) {
      throw '当前数据未提交，请联系管理员提交数据'
    }
    return enumModel.data.data
  }

  /**F
   * 获取历史记录
   */
  public async recordList(id: string, query) {
    const { Data } = this.ctx.model as any;
    return await Data.findRecordWithId(id, query)
  }

  /**
   * 获取历史记录个数
   */
  public async recordCount(id: string) {
    const { Data } = this.ctx.model as any;
    return await Data.findRecordCountWithId(id)
  }

  /**
   * 删除单条记录
   */
  public async recordRemove(id) {
    const { Data } = this.ctx.model as any;
    await Data.removeWithId(id)
  }

  /**
   * 恢复单条数据
   */
  public async restoreOne(id) {
    const { Data } = this.ctx.model as any;
    // 获取历史数据
    const hisData = await Data.findWithId(id)
    // 获取当前数据
    const currentData = await Data.findWithId(hisData.superId)
    // 修改当前数据
    await this.restoreData(currentData, hisData.data)
    return currentData
  }

  /**
   * 数组添加单条数据
   */
  public async arrayPush(enumId: string, { data, index }) {
    const { Enum } = this.ctx.model as any;
    // 获取enum数据
    const enumModel = await Enum.findWithId(enumId)
    // 先创建数据
    await this.createDataModel(data, enumModel.project, enumId, index, enumId)
    return enumModel
  }

  /**
   * 获取数组列表
   */
  public async arrayList(superId: string, query) {
    const { Data } = this.ctx.model as any;
    return await Data.findDataArrWithSuperId(superId, query)
  }

  /**
   * 获取个数
   */
  public async arrayListCount(superId: string, query) {
    const { Data } = this.ctx.model as any;
    return await Data.findDataArrCountWithSuperId(superId, query)
  }

  /**
   * 获取数组列表
   */
  public async arrayListWithUUID(uuid: string, query) {
    const { Data, Enum } = this.ctx.model as any;
    const superId = await Enum.getIdWithUUID(uuid)
    const dataArr = await Data.getDataArrWithSuperId(superId, query)
    return dataArr
  }

  /**
   * 数组添加单条数据
   */
  public async arrayListCountWithUUID(uuid: string, query) {
    const { Data, Enum } = this.ctx.model as any;
    const superId = await Enum.getIdWithUUID(uuid)
    return await Data.findDataArrCountWithSuperId(superId, query)
  }

  /**
   * 更新列表中的数据
   */
  public async arrayListUpdate(id: string, { data, index }) {
    const { Data } = this.ctx.model as any;
    // 获取数据
    const currentData = await Data.findWithId(id)
    // 创建记录
    await this.restoreData(currentData, data, index)
    return currentData
  }

  /**
   * 修改状态（添加回收站，从回收站删除）
   */
  public async arrayListRecycle(id: string, isAdd = true) {
    const { Data } = this.ctx.model as any;
    await Data.updateWithId(id, {
      status: isAdd ? ModelStatus.DELETE : ModelStatus.NORMAL
    })
  }

  /**
   * 删除数据还有他的记录数据
   */
  public async remove(id) {
    const { Data } = this.ctx.model as any;
    // 删除当前数据
    await Data.removeWithId(id)
    // 删除所有记录
    await Data.removeWithQuery({
      superId: id
    })
  }
}
